#include<iostream>
#include<cassert>
#include<cstdio>
#include<string>
#include<cstring>
#include<cassert>
#include<vector>
#include<unistd.h>
#include<pthread.h>
#include<memory>
#include"Mutex.hpp"
// #include"Thread.hpp"
using namespace std;
pthread_mutex_t lock=PTHREAD_MUTEX_INITIALIZER;//全局锁不需要再destroy
//新线程
// void* thread_routine(void* args)
// {
//     while(true)
//     {
//         const char* name=(const char*)args;
//         cout<<"我是新线程，我正在运行! name:"<<name<<endl;
//         sleep(1);
//     }
// }
// int main()
// {
//     pthread_t tid;//其实是一个地址//pthread_t是无符号整型
//     int n=pthread_create(&tid,nullptr,thread_routine,(void*)"thread one");
//     assert(0==n);
//     (void)n;
//     //主线程
//     while(true)
//     {
//         cout<<"我是主线程，我正在运行!,我创建的线程id"<<tid<<endl;
//         sleep(1);
//     }
//     return 0;
// }
//当结构体用
// class ThreadData
// {
// public:
//     pthread_t tid;
//     char namebuffer[64];
//     int number;
// };
// class ThreadReturn
// {
// public:
//     int exit_code;
//     int exit_result;

// };
// //1.start_routine被十个进程同时执行，状态：重入状态
// //2.该函数是可重入函数
// void *start_routine(void* args)
// {
//     //exit不能用来终止线程，因为exit是用来终止进程的，任何一个执行流调用时，进程终止
//     sleep(1);
//     //string name=static_cast<const char*>(args);//安全的进行强制类型转化
//     ThreadData* td=static_cast<ThreadData *>(args);
//     int cnt=10;
//     while(cnt)
//     {
//         cout<<"我是新线程，我正在运行! name:"<<td->namebuffer<<"cnt:"<<cnt--<<endl;
//         sleep(1);
       
//     }
//     // delete td;
//     //pthread_exit(nullptr);//终止进程
//     //return nullptr;//线程函数结束，return时就算终止了
//     //return (void*)td->number;//既然返回假的地址，整数都能被拿到，那么堆空间地址，对象地址一样可以拿到
//     ThreadReturn *tr=new ThreadReturn();
//     tr->exit_code=1;
//     tr->exit_result=106;
//     return (void*)tr;
// }


// //创建一批线程
// int main()
// {
//     vector<ThreadData*> threads;
// #define NUM 10
    
//     for(int i=0;i<NUM;i++)
//     {
//     ThreadData *td=new ThreadData();
//     snprintf(td->namebuffer,sizeof(td->namebuffer),"%s:%d","thread",i);
//     td->number=i;
//     pthread_create(&(td->tid),nullptr,start_routine,td);
//     threads.push_back(td);
//     }
//     for(auto &iter:threads)
//     {
//         cout<<"create thread: "<<iter->namebuffer<<":"<<iter->tid<<"sucess"<<endl;
//     }
//     //线程是可以被cancel取消的，注意事项：线程要被取消，前提是这个线程已经跑起来了
//     // sleep(5);
//     // for(int i=0;i<threads.size()/2;i++)
//     // {
//     //     pthread_cancel(threads[i]->tid);
//     //     cout<<"pthread_cancel:"<<threads[i]->namebuffer<<"sucess"<<endl;
//     // }//线程如果是被取消的，退出码为-1
//     for(auto &iter:threads)
//     {
//         ThreadReturn *ret=nullptr;
//         //为什么没有见到线程退出时候，对应的退出信号：线程出异常，收到信号，整个进程都会退出
//         //篇thread_join不关心异常问题，异常是进程考虑的
//         int n=pthread_join(iter->tid,(void**)&ret);
//         assert(n==0);
//         cout<<"join sucess"<<"退出信息"<<ret->exit_code<<ret->exit_result<<endl;
//         delete iter;
//     }
//     cout<<"main thread quit..."<<endl;
//     // while(true)
//     // {
//     //     cout<<"我是主线程"<<endl;
//     //     sleep(1);
//     // }
//     return 0;
// }

//学习分离线程
// std::string changeId(const pthread_t &thread_id)
// {
//     char tid[128];
//     snprintf(tid,sizeof(tid),"0x%x",thread_id);
//     return tid;
// }
// void* start_routine(void* args)
// {
//     std::string threadname=static_cast<const char*>(args);
//     //pthread_detach(pthread_self());//设置自己为分离状态
//     int cnt=5;
//     while(cnt--)
//     {

//         cout<<threadname<<"running..."<<changeId(pthread_self())<<endl;
//         sleep(1);
//     }
// }
// void *thread_run(void* args)
// {
//     std::string work_type=static_cast<const char*>(args);
//     while(true)
//     {
//         std::cout<<"我是一个新进程，我正在做："<<work_type<<std::endl;
//         sleep(1);
//     }
// }
//用锁时，要保证临界区粒度尽量小
class threadData
{
public:
    threadData(const std::string &threadname,pthread_mutex_t *mutex_p)
    :threadname_(threadname)
    ,mutex_p_(mutex_p)
    {

    }
public:
    std::string threadname_;
    pthread_mutex_t *mutex_p_;
};

int tickets=200;
//1.锁本身就是共享资源，全局变量是要被保护的，所是用来保护全局资源
//上锁和解锁过程必须安全，其实是原子的
//申请锁没有成功，执行流会阻塞
//谁持有锁，谁进入临界区
void* getTicket(void* args)
{
    threadData* td=static_cast<threadData *>(args);
    
    while(true)
    {
        //加锁和解锁是多个过程串行执行的，程序变慢了
        //锁只规定互斥访问，没有规定谁先执行
        //锁就是多个执行流进行竞争的结果
        // pthread_mutex_lock(td->mutex_p_);
        {//构建的新代码块，括号结束，自动析构解锁
            LockGuard lockguard(&lock);
        if(tickets > 0)
        {
            usleep(1254);
            std::cout<<td->threadname_<<"正在进行抢票:"<<tickets<<std::endl;
            tickets--;
            //pthread_mutex_unlock(&lock);
        }
        else{
               //pthread_mutex_unlock(&lock);
            break;
        }
        }
        //usleep(1000);//模拟去做其他事情
    }
    return nullptr;
}

int main()
{
#define NUM 4
    // pthread_mutex_t lock;
    // pthread_mutex_init(&lock,nullptr);
    
    std::vector<pthread_t> tids(NUM);
    for(int i=0;i<=4;i++)
    {
        char buffer[64];
        snprintf(buffer,sizeof(buffer),"thread %d",i+1);
        threadData* td=new threadData(buffer,&lock);
        pthread_create(&tids[i],nullptr,getTicket,td);
    }
    for(const auto &tid:tids)
    {
        pthread_join(tid,nullptr);
    }
    // pthread_mutex_destroy(&lock);
    // pthread_t t1,t2,t3,t4;
    // pthread_create(&t1,nullptr,getTicket,(void*)"thread 1");
    // pthread_create(&t2,nullptr,getTicket,(void*)"thread 2");
    // pthread_create(&t3,nullptr,getTicket,(void*)"thread 3");
    // pthread_create(&t4,nullptr,getTicket,(void*)"thread 4");
    // pthread_join(t1,nullptr);
    // pthread_join(t2,nullptr);
    // pthread_join(t3,nullptr);
    // pthread_join(t4,nullptr);

    // std::unique_ptr<Thread> thread1(new Thread(thread_run,(void*)"hellothread",0));
    // std::unique_ptr<Thread> thread2(new Thread(thread_run,(void*)"countthread",0));
    // std::unique_ptr<Thread> thread3(new Thread(thread_run,(void*)"logthread",0));
    // thread1->join();
    // thread2->join();
    // thread3->join();
    // pthread_t tid;
    // pthread_create(&tid,nullptr,start_routine,(void*)"thread one");
    // std::string main_id=changeId(pthread_self());
    // pthread_detach(pthread_self());
    // std::cout<<"main thread rinning..."<<changeId(tid)<<"main thread id:"<<main_id<<std::endl;
    // //一个线程默认是joinable的，如果设置了分离状态，不能进行等待了
    // int n=pthread_join(tid,nullptr);
    // std::cout<<"result: "<<n<<":"<<strerror(n)<<std::endl;
    // return 0;
}